package websockethttp

import (
	"crypto/rand"
	"encoding/base64"
	"fmt"
	"github.com/gorilla/websocket"
	"log"
)

const (
	PongProcessName       = "Health"
	PongProcessTime       = 4500
	PongProcessSuccess    = 0
	RequestTimeoutCode    = -500
	RequestTimeoutMsg     = "timeout"
	RequestDefaultTimeout = int64(60 * 1000)
)

// SocketRequest {"U":"","P":"","H":{},"B":""}
type SocketRequest struct {
	Uid     string            `json:"U"` // 消息唯一ID
	Process string            `json:"P"` // 处理器
	Header  map[string]string `json:"H"` // 数据头
	Body    string            `json:"B"` // 数据体（需要进行编码后传输）
}

// SocketResponse {"U":"","C":"","M":"","H":{},"B":""}
type SocketResponse struct {
	Uid     string            `json:"U"` // 消息唯一ID
	Code    int               `json:"C"` // 业务状态
	Message string            `json:"M"` // 业务说明
	Header  map[string]string `json:"H"` // 数据头
	Body    string            `json:"B"` // 数据体（需要进行编码后传输）
}

// RequestNew 新建一个请求体
func RequestNew(process string, header map[string]string, body string) *SocketRequest {
	req := new(SocketRequest)
	req.Uid = NewMessageId()
	req.Process = process
	req.Header = header
	req.Body = body
	return req
}

// ResponseNew 新建一个响应体
func ResponseNew(code int, message string, header map[string]string, body string) *SocketResponse {
	res := new(SocketResponse)
	res.Uid = NewMessageId()
	res.Code = code
	res.Message = message
	res.Header = header
	res.Body = body
	return res
}

// 生成作为消息UID的UUID Reference：https://github.com/go-basic/uuid
func generateUUID() (string, error) {
	buf := make([]byte, 16)
	_, _ = rand.Read(buf)
	return fmt.Sprintf("%s%s%s%s%s", // %x-%x-%x-%x-%x
		buf[0:4],
		buf[4:6],
		buf[6:8],
		buf[8:10],
		buf[10:16],
	), nil
}

// NewMessageId 创建一个消息ID
func NewMessageId() string {
	uuid, err := generateUUID()
	if err != nil {
		return ""
	}
	return base64.StdEncoding.EncodeToString([]byte(uuid)) // 使用base64压缩 w38NHWeXJaOR82FATR0zQw==
}

// 安全的关闭channel操作
func safeCloseClientContextChannel(channel chan *ClientContext) {
	defer func() {
		recover()
	}()
	close(channel)
}

// 安全的关闭channel操作
func safeCloseServerContextChannel(channel chan *ServerContext) {
	defer func() {
		recover()
	}()
	close(channel)
}

func writeRequestMessage(conn *websocket.Conn, message []byte) error {
	err := conn.WriteMessage(websocket.TextMessage, message)
	if err != nil {
		log.Printf("writeRequestMessage: 向客户端发送 Request 失败 %s", string(message))
	}
	return err
}

func writeResponseMessage(conn *websocket.Conn, message []byte) error {
	err := conn.WriteMessage(websocket.BinaryMessage, message)
	if err != nil {
		log.Printf("writeResponseMessage: 向客户端发送 Response 失败 %s", string(message))
	}
	return err
}

//type CommonFunc interface {
//	AddClientRequestFilterFunc() todo
//	AddClientResponseFilterFunc() todo
//	AddServerRequestFilterFunc() todo
//	AddServerResponseFilterFunc() todo
//	SetRequestCommonHeader() todo
//	SetResponseCommonHeader()
//	SetRequestTimeout()
//	ShowPongLogs() todo
//	RegisterProcessFunc() todo
//	SetWriteBeforeFunc()
//	SetReadBeforeFunc()
//	SetDefaultProcessFunc()
//	CloseConnection()	todo
//	SendMessage()
//	SendMessageSync()
//}
//
//type ServerFunc interface {
//	CommonFunc
//	SetAuthorizationFunc()
//	AddConnOpenEventFunc()
//	AddConnCloseEventFunc()
//	GetClientChannel()
//	GetAllClientChannel()
//	SetWebsocketUpgrader()
//}
//
//type ClientFunc interface {
//	CommonFunc
//	SetPongTime()
//	IsActiveStatus()
//}
